﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.ServiceModel.Activation;
using System.Web;
using Odin.Contracts.Data;
using Odin.Contracts.Services;

namespace Odin.Execution.Services
{
	public class RemoteSessionManagerData
	{
		public const string SessionsKey = "Sessions";
		public static readonly RemoteSessionManagerData Instance = new RemoteSessionManagerData();

		public Dictionary<string, Session> Sessions;

		private RemoteSessionManagerData()
		{
			var sessions = HttpContext.Current.Application[SessionsKey];
			if( null == sessions )
			{
				Sessions = new Dictionary<string, Session>();
				HttpContext.Current.Application[SessionsKey] = Sessions;
			} else
			{
				Sessions = sessions as Dictionary<string, Session>;
				
			}
		}
	}


	[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
	public class RemoteSessionManager : IRemoteSessionManager
	{
		

		public void BeginSession(Session session)
		{
			RemoteSessionManagerData.Instance.Sessions[session.Identifier] = session;

		}

		public void EndSession(Session session)
		{
			RemoteSessionManagerData.Instance.Sessions.Remove(session.Identifier);
		}

		public Session GetSessionByIdentifier(string identifier)
		{
			var session = RemoteSessionManagerData.Instance.Sessions[identifier];
			return session;
		}

		public Session UpdateSession(Session session)
		{
			if (!RemoteSessionManagerData.Instance.Sessions.ContainsKey(session.Identifier))
			{
				RemoteSessionManagerData.Instance.Sessions[session.Identifier] = session;
			}
			return RemoteSessionManagerData.Instance.Sessions[session.Identifier];
		}

		public void ReportMethod(Session session, Method method)
		{
			var found = false;
			foreach (var existingMethod in session.Methods)
			{
				if (existingMethod.Namespace.Equals(method.Namespace) &&
					existingMethod.Class.Equals(method.Class) &&
					existingMethod.MethodName.Equals(method.MethodName))
				{
					existingMethod.Result = method.Result;
					existingMethod.Message = method.Message;
					existingMethod.StackTrace = method.StackTrace;
					existingMethod.LastModified = DateTime.Now;
					found = true;
					break;
				}
			}
			if (!found)
			{
				method.LastModified = DateTime.Now;
				session.Methods.Add(method);
			}
			RemoteSessionManagerData.Instance.Sessions[session.Identifier] = session;
		}

		public void Running(Session session)
		{
			RemoteSessionManagerData.Instance.Sessions[session.Identifier].Status = SessionStatus.Running;
		}

		public void Completed(Session session)
		{
			RemoteSessionManagerData.Instance.Sessions[session.Identifier].Status = SessionStatus.Completed;
		}

		public Method[] GetMethodsChangedSince(Session session, DateTime dateTime)
		{
			var sessionToCheck = GetSessionByIdentifier(session.Identifier);
			var query = from m in sessionToCheck.Methods
			            where m.LastModified >= dateTime 
			            select m;
			return query.ToArray();
		}
	}
}
